/*
Javier Kohen's Java Framework Classes.
Copyright (C) 2000-2001  Javier Kohen <jkohen at tough.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package ar.com.jkohen.awt;

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Vector;

import ar.com.jkohen.awt.TextFieldHistory;
import ar.com.jkohen.irc.MircMessage;
import ar.com.jkohen.util.Resources;
import com.splendid.awtchat.SmileyTextArea;

public class TextAttributePicker extends Dialog implements KeyListener, MouseListener, MouseMotionListener
{
	private TextField tf;

	private int current_foreground = 0;

    private static Vector items;
	private static int order[];
    private String action_command;

    private Dimension item_size;
    private Dimension disposition;
    private Dimension gap;

    private Image image;
    private Graphics img_gfx;

    public TextAttributePicker(Frame f, TextField tf, Dimension disposition, Dimension item_size, Dimension gap)
	{
		super(f);
		this.tf = tf;
		
		Color colors[] = SmileyTextArea.getColorPalette();
/*
    	GridBagLayout gb = new GridBagLayout();
    	GridBagConstraints gbc = new GridBagConstraints();

    	setLayout(gb);

    	reset = new ImageButton(false);
    	reset.setIcon(Resources.getImage("picker.regular"));
     	add(reset);

    	bold = new ImageButton(false);
    	bold.setIcon(Resources.getImage("picker.bold"));
		add(bold);

    	under = new ImageButton(false);
    	under.setIcon(Resources.getImage("picker.under"));
    	add(under);

    	italic = new ImageButton(false);
    	italic.setIcon(Resources.getImage("picker.italic"));
    	add(italic);

		reverse = new ImageButton(false);
    	reverse.setIcon(Resources.getImage("picker.reverse"));
    	add(reverse);
    	
    	gbc.weightx = 1.0;
    	gb.setConstraints((Component) color_picker, gbc);
    	add((Component) color_picker);
*/
		this.disposition = disposition;
		this.item_size = item_size;
		this.gap = gap;
		this.action_command = "";

//		this.items = new Vector(colors.length);
//		setColors(colors);

    	/* Event listeners.
    	 */
/*
    	reset.addActionListener(this);
    	bold.addActionListener(this);
    	under.addActionListener(this);
    	italic.addActionListener(this);
    	reverse.addActionListener(this);
    	color_picker.addActionListener(this);
*/
		addMouseListener(this);
		addMouseMotionListener(this);
		addKeyListener(this);
		
		setBackground(f.getBackground());
		
		pack();
		setResizable(false);
		show();
		requestFocus();
	}

	public void setTextField(TextField tf)
    {
		this.tf = tf;
    }
	
    public Color [] getColors()
    {
		Color [] colors = new Color [items.size()];
		items.copyInto(colors);

		return(colors);
    }

    public static void setColors(Color [] colors)
    {
		items = new Vector(colors.length);
		items.removeAllElements();

		for (int i = 0; i < colors.length; i++)
		    items.addElement(colors[i]);
    }

	public static void setOrder(int o[])
    {
		order = o;
		Vector v = new Vector(o.length);
		for (int i = 0; i < o.length; i++)
		    v.addElement(items.elementAt(i));

		for (int i = 0; i < o.length; i++)
			items.setElementAt(v.elementAt(i), o[i]);
	}
/*	
    public void actionPerformed(ActionEvent ev)
	{
		Object source = ev.getSource();
		String text_attr = "";

		System.out.println(source.toString());
		
    	if (source.equals(this))
    	{
    	    Color c = getSelected();
    	    int ci = getSelectedIndex();
//			int ci = c.getRGB();
    	    int modifiers = ev.getModifiers();

    	    if ((MouseEvent.BUTTON1_MASK & modifiers) != 0 || modifiers == 0)
    		{
    			// WORKAROUND: #32 Netscape Navigator doesn't set it right for BUTTON1.
    			text_attr = String.valueOf(ci);
				current_foreground = ci;
    	    }
    		else if ((MouseEvent.BUTTON3_MASK & modifiers) != 0)
    		{
    			text_attr = current_foreground + "," + ci;
    	    }
    	}
    	else if (source.equals(bold))
    	{
    	   	text_attr = MircMessage.attrEncode(MircMessage.BOLD);
    	}
    	else if (source.equals(under))
    	{
    	   	text_attr = MircMessage.attrEncode(MircMessage.UNDERLINE);
    	}
    	else if	(source.equals(italic))
    	{
     	   text_attr = MircMessage.attrEncode(MircMessage.ITALIC);
    	}
    	else if (source.equals(reset))
    	{
        	text_attr = MircMessage.attrEncode(MircMessage.RESET);
    	}
    	else if (source.equals(reverse))
    	{
        	text_attr = MircMessage.attrEncode(MircMessage.REVERSE);
    	}
    	
    	processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, text_attr, ev.getModifiers()));
    }
*/	
	public void setBackground(Color c)
    {
        super.setBackground(c);
/*
		reset.repaint();
		bold.repaint();
		under.repaint();
		italic.repaint();
		reverse.repaint();
*/
		repaint();
    }

    public Dimension getItemSize()
    {
		return(item_size);
    }

    public void setItemSize(Dimension d)
    {
		item_size.setSize(d.width, d.height);
    }

    public Dimension getDisposition()
    {
		return disposition;
    }

    protected Dimension getRealDisposition()
    {
		Dimension r = disposition;

		if (r.width == 0 && r.height == 0)
		{
		    r.width = r.height = (int) Math.sqrt(items.size() - 1) + 1;
		}
		else if (r.width == 0)
		{
		    r.width = (items.size() - 1) / r.height + 1;
		}
		else if (r.height == 0)
		{
		    r.height = (items.size() - 1) / r.width + 1;
		}

		return(r);
    }

    public void setDisposition(Dimension d)
    {
		disposition.setSize(d.width, d.height);
    }

    public Dimension getGap()
    {
		return(gap);
    }

    public void setGap(Dimension d)
    {
		gap.setSize(d.width, d.height);
    }

    /**
     * If <code>gap</code> is big enough, user will notice this method is not exact.
     */
    private int getItemAt(Point p)
    {
    	Dimension real = getRealDisposition();

    	int i = p.x / (item_size.width + gap.width);
    	int j = p.y / (item_size.height + gap.height);

		int index = ((i * real.height + j) - 1);
		
		for (int k = 0; k < order.length; k++)
			if (index == order[k])
				return(k);
				
    	return(-1);
    }
/*
    public int getSelectedIndex()
    {
	    return last_selected;
    }

    public void setSelectedIndex(int i)
    {
		this.last_selected = i;
    }

    public Color getSelected()
    {
		return (Color) items.elementAt(last_selected);
    }

    public void setSelected(Color c)
    {
		this.last_selected = items.indexOf(c);
    }
*/


    private void createImageBuffer(Dimension size)
    {
		image = createImage(size.width, size.height);
		if (img_gfx != null)
		    img_gfx.dispose();

		img_gfx = image.getGraphics();
   	}

    public void update(Graphics g)
	{
		paint(g);
    }

    public void paint(Graphics g)
	{
    	Dimension size = getSize();

    	if (img_gfx == null || image.getWidth(this) != size.width || image.getHeight(this) != size.height)
    	    createImageBuffer(size);

    	Dimension real_disposition = getRealDisposition();
		int x = 0, y = 0;
/*
		for (int i = 0; i < real_disposition.width; i++)
		{
			y = 0;
			
			for (int j = 0; j < real_disposition.height; j++)
			{
				int index = i * real_disposition.height + j;
    			if (index >= 5)
    		    	break;
			
				img_gfx.setColor(Color.black);
				img_gfx.fillRect(x + 2, y + 2, item_size.width - 2, item_size.height - 2);
				img_gfx.setColor(Color.white);
				img_gfx.fillRect(x, y, item_size.width - 1, item_size.height - 1);
				img_gfx.setColor(Color.black);
				img_gfx.drawString("A", x + 2, y + getFont().getSize());
				
				y += gap.height + item_size.height;
			}
			x += gap.width + item_size.width;
		}

    	x = 0;
*/
    	for (int i = 0; i < real_disposition.width; i++)
		{
//    	    y = gap.height + item_size.height;
			y = 0;

    	    for (int j = 0; j < real_disposition.height; j++)
			{
    			int index = i * real_disposition.height + j;
    			if (index >= items.size())
    		    	break;

	    		img_gfx.setColor(Color.black);
    			img_gfx.fillRect(x + 2, y + 2, item_size.width - 2, item_size.height - 2);
    			
	    		img_gfx.setColor((Color) items.elementAt(index));
    			img_gfx.fillRect(x, y, item_size.width - 1, item_size.height - 1);
				
				if (index <= 9)
					index += 0x30;
				else
					index += 0x37;
				img_gfx.setColor(new Color(0xCC, 0xCC, 0xCC));
				img_gfx.drawString(String.valueOf((char)index), x + 2, y + getFont().getSize());

	    		y += gap.height + item_size.height;
    	    }
	   	    x += gap.width + item_size.width;
    	}
		
	   	g.drawImage(image, getInsets().left, getInsets().top, this);
    }

    public String getActionCommand()
	{
		return action_command;
    }

    public void setActionCommand(String action)
	{
		this.action_command = action;
    }
	
	public void keyPressed(KeyEvent ev)
	{
		char ch = Character.toUpperCase(ev.getKeyChar());
   		if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F'))
		{
			if (ch <= '9')
				ch -= 0x30;
			else
				ch -= 0x37;
				
			int index = 1;
			for (int k = 0; k < order.length; k++)
				if (ch == order[k])
					index = k;
				
			setActionCommand(String.valueOf(index));
			TextFieldHistory tfh = (TextFieldHistory)tf;
			if (tfh != null)
				tfh.insert(MircMessage.COLOR + action_command);
				
			return;
		}
		
		dispose();
    }
	
	public void keyReleased(KeyEvent e)
	{
    }

    public void keyTyped(KeyEvent e)
	{
    }

	public void mouseDragged(MouseEvent ev)
	{
	}
	
	public void mouseMoved(MouseEvent ev)
	{
		if(getItemAt(ev.getPoint()) >= 0)
	    	setCursor(new Cursor(Cursor.HAND_CURSOR));
		else
			setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
	}
	
    public void mouseClicked(MouseEvent ev)
	{
    }

    public void mousePressed(MouseEvent ev)
    {
    }

    public void mouseReleased(MouseEvent ev)
	{
		int index = getItemAt(ev.getPoint());
		if (index == -1)
			return;
			
		if ((ev.getModifiers() & MouseEvent.BUTTON3_MASK) == 0)
			setActionCommand(String.valueOf(index));
			
		if ((ev.getModifiers() & MouseEvent.BUTTON3_MASK) != 0)
			setActionCommand(0 + "," + index);

		TextFieldHistory tfh = (TextFieldHistory)tf;
		if (tfh != null)
			tfh.insert(MircMessage.COLOR + action_command);
		
//		processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, action_command, ev.getModifiers()));

		// Avoid taking mouse focus.
		ev.consume();
   }

    public void mouseEntered(MouseEvent ev)
    {
	}

    public void mouseExited(MouseEvent ev)
    {
    	setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }

	public void show()
	{
		setLocation(new Point(tf.getLocationOnScreen().x, tf.getLocationOnScreen().y + tf.getSize().height));
		super.show();
	}
	
	public Insets getInsets()
	{
		Insets i = super.getInsets();
		return (new Insets(i.top + 2, i.left + 2, i.bottom + 2, i.right + 2));
	}
	
    public Dimension getMinimumSize()
    {
		return getPreferredSize();
    }

    public Dimension getPreferredSize()
    {
		Dimension real = getRealDisposition();
		Insets insets = getInsets();
		int attributes_height = item_size.height + gap.height;

		return(new Dimension(insets.left + insets.right + (item_size.width * real.width) + gap.width * (real.width - 1), insets.top + insets.bottom + (item_size.height * real.height) + gap.height * (real.height - 1)));
    }
}
